package cn.itcast.zt.config;

import cn.itcast.zt.endpoint.FunctionalEndpoint;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldDefaults;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;

import java.util.HashMap;
import java.util.Map;

/**
 * @author zhangtian105
 * @ClassName FunctionakEndpointConfig.java
 * @projectName SpringBoot2.x
 * @Description 函数式端点
 * https://blog.csdn.net/csdn6497/article/details/104118802
 * 在spring-webflux中已经实现了两条腿走路。采用了函数式和@Controller两种模式。在5.2版本中，spring-mvc也支持了函数式端点
 * @createTime 2020年05月19日 14:12:00
 */
@RequiredArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
@Configuration
@Slf4j
public class FunctionakEndpointConfig {
    FunctionalEndpoint functionalEndpoint;

    @Bean
    public RouterFunction<ServerResponse> functionalEndpointRouterFunction() {
        return RouterFunctions.route()
                .GET("/", functionalEndpoint::index)
                .GET("/me", functionalEndpoint::me)
                .POST("/post-json", functionalEndpoint::postJson)
                .POST("/post-form", functionalEndpoint::postForm)
                .GET("/redirect", functionalEndpoint::redirect)
                .build();
    }

    @Bean
    public RouterFunction<ServerResponse> lambdaRouterFunction() {
        return RouterFunctions.route()
                .POST("/users", request -> {
                    return ServerResponse.ok().build();
                })
                .before(serverRequest -> {
                    // 最先执行,以便于包装 serverRequest
                    log.info("before");
                    return serverRequest;
                })
                .after((serverRequest, serverResponse) -> {
                    // 最后执行,以便于包装serverResponse
                    log.info("after");
                    return serverResponse;
                })
                .filter((request, next) -> {
                    // 中间执行,此处获取到的request是在before中增强过的
                    // 与servlet的filter类似，实现过滤的功能
                    log.info("filter");
                    return next.handle(request);
                })
                .build();
    }

    @Bean
    public RouterFunction<ServerResponse> errorRouterFunction() throws IllegalAccessError {
        return RouterFunctions.route()
                .POST("/errors", request -> {
                    log.error("异常处理......");
                    Map<String, String> map = new HashMap<>() ;
                    map.put("10001", "异常......") ;
                    return ServerResponse.ok().bodyValue(map) ;
                })
                // 错误处理，处理所有异常
                // 如果此处不处理异常，异常处理会进入spring-mvc的标准处理流程
                .onError(Exception.class, (throwable, serverRequest) -> {
                    return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
                })
                .build();
    }
}
